package com.fernandomartines.dbcheck.sql;

import com.fernandomartines.dbcheck.graph.element.ModelGraphAttribute;
import com.fernandomartines.dbcheck.graph.element.ModelGraphEntity;
import java.text.SimpleDateFormat;
import java.util.Date;

public class SQLGenerator {

    private static String stringSequence = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    private static String COUNT_SQL_TEMPLATE = "select count(*) as result from __entity.name__;";
    private static String DELETE_SQL_TEMPLATE = "delete from __entity.name__;";
    private static String INSERT_SQL_TEMPLATE = "insert into __entity.name__ (__entity.attributes.name__) values (__entity.attributes.value__);";

    public static Object generateDefaultAttributeValue(ModelGraphAttribute attribute, boolean random) {
        Object result = null;

        String type = attribute.getType().toUpperCase();
        String defaultString = "A";
        int len = 1;

        String[] arr = type.split("\\(");
        if (arr.length > 1) {
            type = arr[0].trim();
            arr = arr[1].split("\\)");
            len = Integer.parseInt(arr[0]);
            if (len < stringSequence.length())
                defaultString = stringSequence.substring(0, len);
            else
                for (int i = 0; i < len / stringSequence.length(); i++)
                defaultString += stringSequence;
        }

        SQLType sqlType = SQLType.getSQLTypeByName(type);

        if (sqlType == SQLType.CHAR)
            result = random ? new Character((char) (Math.random() * (90 - 65) + 65)) : new Character('A');
        else if (sqlType == SQLType.VARCHAR)
            result = defaultString;
        else if (sqlType == SQLType.INT || sqlType == SQLType.INTEGER)
            result = random ? new Integer((int) (Math.random() * 1000)) : new Integer(1);
        else if (sqlType == SQLType.DECIMAL || sqlType == SQLType.FLOAT)
            result = random ? Math.random() * 1000 : 1.0;
        else if (sqlType == SQLType.DATE || sqlType == SQLType.DATETIME || sqlType == SQLType.TIMESTAMP)
            result = random ? new Date(new Date().getTime() - ((int) (Math.random() * 99))) : new Date();
        else
            result = null;
        
        return result;
    }

    public static String createCountStatement(ModelGraphEntity entity) {
        return COUNT_SQL_TEMPLATE.replaceAll("__entity.name__", entity.getName());
    }

    public static String createDeleteStatement(ModelGraphEntity entity) {
        return DELETE_SQL_TEMPLATE.replaceAll("__entity.name__", entity.getName());
    }

    public static String createInsertStatement(ModelGraphEntity entity, ModelGraphAttribute attribute, Object value) {
        String sql = INSERT_SQL_TEMPLATE.replaceAll("__entity.name__", entity.getName());
        String attributes = "", values = ""; int i = 0;
        for (ModelGraphAttribute attr: entity.getAttributes()) {
            attributes += attr.getName();
            if (attr.getName().equals(attribute.getName()))
                values += getSQLValue(value);
            else
                values += getSQLValue(attr.getDefaultValue());
            if (++i < entity.getAttributes().size()) {
                attributes += ", ";
                values += ", ";
            }
        }
        sql = sql.replaceAll("__entity.attributes.name__", attributes);
        sql = sql.replaceAll("__entity.attributes.value__", values);
        return sql;
    }

    private static String getSQLValue(Object o) {
        String result = "";
        if (o == null)
            result = "null";
        else if (o instanceof String)
            result = "'" + ((String) o) + "'";
        else if (o instanceof Date)
            result = "'" + (new SimpleDateFormat("yyyy-MM-dd").format((Date) o)) + "'";
        else
            result = o.toString();
        return result;
    }

}
